package com.xc.ezplan.core.utils;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;

import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.COSObject;
import com.qcloud.cos.model.COSObjectInputStream;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.StorageClass;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.utils.IOUtils;
import com.xc.ezplan.core.domain.TencentStorageConfig;
import com.xc.ezplan.core.enums.TencentRegionEnum;

import com.xc.ezplan.core.exception.BadRequestException;
import lombok.extern.slf4j.Slf4j;

/**
 * @author lixingchen
 * @date 2022/12/07
 * @description 腾讯云存储工具类
 */
@Slf4j
public class TencentCloudUtil {

	private static final String PACKAGE_NAME = "avatar/";

	public static void upload(TencentStorageConfig tencentStorageConfig, String fileName, byte[] bytes) {

		COSClient cosClient = createCosClient(tencentStorageConfig);
		// 这里创建一个 ByteArrayInputStream 来作为示例，实际中这里应该是您要上传的 InputStream 类型的流
		long inputStreamLength = bytes.length;
		InputStream inputStream = new ByteArrayInputStream(bytes);

		ObjectMetadata objectMetadata = new ObjectMetadata();
		// 上传的流如果能够获取准确的流长度，则推荐一定填写 content-length
		// 如果确实没办法获取到，则下面这行可以省略，但同时高级接口也没办法使用分块上传了
		objectMetadata.setContentLength(inputStreamLength);

		PutObjectRequest putObjectRequest = new PutObjectRequest(tencentStorageConfig.getBucket(),
				PACKAGE_NAME + fileName, inputStream, objectMetadata);

		// 设置存储类型（如有需要，不需要请忽略此行代码）, 默认是标准(Standard), 低频(standard_ia)
		// 更多存储类型请参见 https://cloud.tencent.com/document/product/436/33417
		putObjectRequest.setStorageClass(StorageClass.Standard_IA);

		try {
			PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
			System.out.println(putObjectResult.getRequestId());
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BadRequestException(e.getMessage());
		} finally {
			// 确认本进程不再使用 cosClient 实例之后，关闭之
			cosClient.shutdown();
		}
	}

	public static void download(TencentStorageConfig tencentStorageConfig, String fileName, File file) {
		// 调用 COS 接口之前必须保证本进程存在一个 COSClient 实例，如果没有则创建
		// 详细代码参见本页：简单操作 -> 创建 COSClient
		COSClient cosClient = createCosClient(tencentStorageConfig);

		// 存储桶的命名格式为 BucketName-APPID，此处填写的存储桶名称必须为此格式
		// 对象键(Key)是对象在存储桶中的唯一标识。详情请参见
		// [对象键](https://cloud.tencent.com/document/product/436/13324)
		GetObjectRequest getObjectRequest = new GetObjectRequest(tencentStorageConfig.getBucket(),
				PACKAGE_NAME + fileName);
		COSObjectInputStream cosObjectInput = null;

		try {
			COSObject cosObject = cosClient.getObject(getObjectRequest);
			cosObjectInput = cosObject.getObjectContent();
			// 处理下载到的流
			// 这里是直接读取，按实际情况来处理
			byte[] bytes = null;
			bytes = IOUtils.toByteArray(cosObjectInput);

		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BadRequestException(e.getMessage());
		} finally {
			// 用完流之后一定要调用 close()
			try {
				cosObjectInput.close();
			} catch (IOException e) {
				log.error(e.getMessage(), e);
				throw new BadRequestException(e.getMessage());
			}
			// 在流没有处理完之前，不能关闭 cosClient
			// 确认本进程不再使用 cosClient 实例之后，关闭之
			cosClient.shutdown();
		}

	}

	public static void delete(TencentStorageConfig tencentStorageConfig, Collection<String> fileNames) {
		// 调用 COS 接口之前必须保证本进程存在一个 COSClient 实例，如果没有则创建
		// 详细代码参见本页：简单操作 -> 创建 COSClient
		COSClient cosClient = createCosClient(tencentStorageConfig);

		// 存储桶的命名格式为 BucketName-APPID，此处填写的存储桶名称必须为此格式
		// 对象键(Key)是对象在存储桶中的唯一标识。详情请参见
		// [对象键](https://cloud.tencent.com/document/product/436/13324)

		try {
			for (String fileName : fileNames) {
				cosClient.deleteObject(tencentStorageConfig.getBucket(), PACKAGE_NAME + fileName);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new BadRequestException(e.getMessage());
		} finally {

			// 确认本进程不再使用 cosClient 实例之后，关闭之
			cosClient.shutdown();
		}

	}

	public static void pageQuery(TencentStorageConfig tencentStorageConfig) {

	}

	private static COSClient createCosClient(TencentStorageConfig tencentStorageConfig) {
		COSCredentials cred = new BasicCOSCredentials(tencentStorageConfig.getSecretId(),
				tencentStorageConfig.getSecretKey());
		// 2 设置 bucket 的地域, COS 地域的简称请参照
		// https://cloud.tencent.com/document/product/436/6224
		// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题
		// Java SDK 部分。
		ClientConfig clientConfig = new ClientConfig(
				new Region(TencentRegionEnum.find(tencentStorageConfig.getRegion())));
		// 这里建议设置使用 https 协议
		// 从 5.6.54 版本开始，默认使用了 https
		clientConfig.setHttpProtocol(HttpProtocol.https);
		// 3 生成 cos 客户端。
		return new COSClient(cred, clientConfig);
	}
}
